package dxsvalue

import (
	"bufio"
	"bytes"
	"github.com/suiyunonghen/DxCommonLib"
	"io"
)

type JsonReader struct {
	bfReader *bufio.Reader
	buffer   []byte
}

func NewJsonReader(r io.Reader) *JsonReader {
	result := &JsonReader{
		buffer: make([]byte, 0, 128),
	}
	if bfReader, ok := r.(*bufio.Reader); ok {
		result.bfReader = bfReader
	} else {
		result.bfReader = bufio.NewReader(r)
	}
	return result
}

func (r *JsonReader) Reset(reader io.Reader) {
	r.buffer = r.buffer[:0]
	if bfReader, ok := reader.(*bufio.Reader); ok {
		r.bfReader = bfReader
	} else {
		r.bfReader.Reset(reader)
	}
}

func (r *JsonReader) Skip(checkUtf8Bom bool) error {
	if checkUtf8Bom {
		//先检查utf8头部
		if bytes, err := r.bfReader.Peek(3); err != nil {
			return err
		} else if len(bytes) > 2 && bytes[0] == 0xEF && bytes[1] == 0xBB && bytes[2] == 0xBF { //BOM
			r.bfReader.Discard(3)
		}
	}
	for {
		if bytes, err := r.bfReader.Peek(1); err != nil {
			return err
		} else {
			if bytes[0] > 0x20 || bytes[0] != 0x20 && bytes[0] != 0x0A &&
				bytes[0] != 0x09 && bytes[0] != 0x0D {
				return nil
			}
			r.bfReader.Discard(1)
		}
	}
}

func (r *JsonReader) Decode() (*DxValue, error) {
	err := r.Skip(true)
	if err != nil {
		return nil, err
	}
	b, err := r.bfReader.Peek(1)
	if err != nil {
		return nil, err
	}
	switch b[0] {
	case '{':
		r.bfReader.Discard(1)
		return r.decodeJsonObj(nil)
	case '[':
		r.bfReader.Discard(1)
		return r.decodeJsonArray(nil)
	default:
		return nil, ErrInvalidateJson
	}
}

func (r *JsonReader) decodeJsonKey() (string, error) {
	r.buffer = r.buffer[:0]
	var b []byte
	var err error
	for {
		if b, err = r.bfReader.Peek(1); err != nil {
			return "", err
		}
		r.bfReader.Discard(1)
		if b[0] == '"' {
			return string(r.buffer), nil
		}
		r.buffer = append(r.buffer, b[0])
		if b[0] == '\\' { //有转义
			//直接解析转义字符串
			return r.decodeJsonString()
		}
	}
}

func (r *JsonReader) decodeJsonString() (string, error) {
	b, err := r.bfReader.Peek(1)
	if err != nil {
		return "", err
	}
	l := len(r.buffer)
	var lastByte byte
	if l > 0 {
		lastByte = r.buffer[l-1]
	}
	for {
		if b, err = r.bfReader.Peek(1); err != nil {
			return "", err
		}
		r.bfReader.Discard(1)
		if b[0] != '"' {
			lastByte = b[0]
			r.buffer = append(r.buffer, b[0])
			continue
		}
		if lastByte != '\\' { //不是转义的，说明完毕了
			return string(r.buffer), err
		}
		//是转义的，还需要查找上上次，是否是\\
		escapCount := 1
		l = len(r.buffer)
		for i := l - 1; i > 0; i-- {
			if r.buffer[i] != '\\' {
				break
			}
			escapCount++
		}
		if escapCount%2 == 0 { //结束了
			return string(r.buffer), nil
		} else {
			//是转义 \"
			lastByte = '"'
			r.buffer = append(r.buffer, '"')
		}
	}
}

func (r *JsonReader) decodeJsonValue(c *ValueCache) (result *DxValue, err error) {
	r.buffer = r.buffer[:0]
	err = r.Skip(false)
	if err != nil {
		return nil, err
	}
	b, err := r.bfReader.Peek(1)
	if err != nil {
		return nil, err
	}
	switch b[0] {
	case '{':
		r.bfReader.Discard(1)
		return r.decodeJsonObj(c)
	case '[':
		r.bfReader.Discard(1)
		return r.decodeJsonArray(c)
	case '"':
		r.bfReader.Discard(1)
		if strV, err := r.decodeJsonString(); err != nil {
			return nil, err
		} else {
			//先判断一下是否是Json的日期格式
			dt, err := DxCommonLib.ParserJsonTime(strV)
			if err != nil {
				result = c.getValue(VT_String)
				result.fstrvalue = strV
			} else {
				result = c.getValue(VT_DateTime)
				result.SetTime(dt)
			}
			return result, nil
		}
	case 't':
		//true
		b, err = r.bfReader.Peek(4)
		if err != nil {
			return nil, err
		}
		if bytes.Compare(b, truebyte) != 0 {
			return nil, ErrInvalidateJson
		}
		r.bfReader.Discard(4)
		return valueTrue, nil
	case 'f':
		//false
		b, err = r.bfReader.Peek(5)
		if err != nil {
			return nil, err
		}
		if bytes.Compare(b, falebyte) != 0 {
			return nil, ErrInvalidateJson
		}
		r.bfReader.Discard(5)
		return valueFalse, nil
	case 'n':
		//null,nan
		b, err = r.bfReader.Peek(4)
		if err != nil {
			return nil, err
		}
		if bytes.Compare(b, nullbyte) != 0 {
			//判定一下是否是NAN
			if bytes.Compare(b[:3], nanbyte) != 0 {
				return nil, ErrInvalidateJson
			}
			r.bfReader.Discard(3)
			return valueNAN, nil
		}
		r.bfReader.Discard(4)
		return valueNull, nil
	default:
		//num
		return r.decodeJsonNum(c)
	}
}

func (r *JsonReader) decodeJsonNum(c *ValueCache) (num *DxValue, err error) {
	readBuffer := r.buffer[:0]
	isFloat := false
	i := 0
	var b []byte
	for {
		b, err = r.bfReader.Peek(1)
		if err != nil {
			return nil, err
		}
		if !isFloat {
			isFloat = b[0] == '.'
		}
		if (b[0] >= '0' && b[0] <= '9') || b[0] == '.' || b[0] == '-' || b[0] == 'e' || b[0] == 'E' || b[0] == '+' {
			r.bfReader.Discard(1)
			readBuffer = append(readBuffer, b[0])
			i++
			continue
		}
		if i == 0 || i == 1 && (b[0] == '-' || b[0] == '+') {
			r.bfReader.Discard(1)
			i++
			//判定是否是有效的数字
			b, err = r.bfReader.Peek(4)
			if err != nil {
				return nil, err
			}
			if len(b) >= 3 {
				if bytes.EqualFold(b[:3], infbyte) {
					return valueINF, nil
				}
				if bytes.EqualFold(b[:3], nanbyte) {
					return valueNAN, nil
				}
			}
			return nil, ErrInvalidateJson
		}
		i++
		//numEnd
		if isFloat {
			v := DxCommonLib.StrToFloatDef(DxCommonLib.FastByte2String(readBuffer), 0)
			num = c.getValue(VT_Double)
			num.SetDouble(v)
		} else {
			v := DxCommonLib.StrToIntDef(DxCommonLib.FastByte2String(readBuffer), 0)
			num = c.getValue(VT_Int)
			num.SetInt(v)
		}
		return num, nil
	}
}

func (r *JsonReader) decodeJsonArray(c *ValueCache) (*DxValue, error) {
	err := r.Skip(false)
	if err != nil {
		return nil, err
	}
	b, err := r.bfReader.Peek(1)
	if err != nil {
		return nil, err
	}
	var result *DxValue
	if c == nil {
		result = NewCacheValue(VT_Array)
	} else {
		result = c.getValue(VT_Array)
	}
	if b[0] == ']' {
		return result, nil
	}

	for {
		err = r.Skip(false)
		if err != nil {
			FreeValue(result)
			return nil, err
		}
		v, err := r.decodeJsonValue(c)
		if err != nil {
			FreeValue(result)
			return nil, err
		}
		result.farr = append(result.farr, v)
		err = r.Skip(false)
		if err != nil {
			FreeValue(result)
			return nil, err
		}
		b, err = r.bfReader.Peek(1)
		if err != nil {
			FreeValue(result)
			return nil, err
		}
		if len(b) == 0 {
			FreeValue(result)
			return nil, ErrInvalidateJson
		}
		if b[0] == ',' {
			r.bfReader.Discard(1)
			continue
		}
		if b[0] == ']' {
			r.bfReader.Discard(1)
			return result, nil
		}
		FreeValue(result)
		return nil, ErrInvalidateJson
	}
}

func (r *JsonReader) decodeJsonObj(c *ValueCache) (*DxValue, error) {
	err := r.Skip(false)
	if err != nil {
		return nil, err
	}
	var result *DxValue
	if c == nil {
		result = NewCacheValue(VT_Object)
	} else {
		result = c.getValue(VT_Object)
	}
	b, err := r.bfReader.Peek(1)
	if err != nil {
		FreeValue(result)
		return nil, err
	}
	if b[0] == '}' {
		r.bfReader.Discard(1)
		return result, nil
	}
	//result.fobject.keysUnescaped = true
	for {
		kv := result.fobject.getKv()
		if err = r.Skip(false); err != nil {
			FreeValue(result)
			return nil, err
		}
		if b, err = r.bfReader.Peek(1); err != nil {
			FreeValue(result)
			return nil, err
		}
		if b[0] != '"' {
			return nil, ErrInvalidateJson
		}
		r.bfReader.Discard(1)
		//读取key
		key, err := r.decodeJsonKey()
		if err != nil {
			FreeValue(result)
			return nil, err
		}
		kv.K = key
		if err = r.Skip(false); err != nil {
			FreeValue(result)
			return nil, err
		}
		//分隔符:
		if b, err = r.bfReader.Peek(1); err != nil {
			FreeValue(result)
			return nil, err
		}
		if err != nil || b[0] != ':' {
			FreeValue(result)
			return nil, ErrInvalidateJson
		}
		r.bfReader.Discard(1)
		//读取value
		v, err := r.decodeJsonValue(c)
		if err != nil {
			FreeValue(result)
			return nil, err
		}
		kv.V = v
		if err = r.Skip(false); err != nil {
			FreeValue(result)
			return nil, err
		}
		//判定是否还有,
		if b, err = r.bfReader.Peek(1); err != nil {
			FreeValue(result)
			return nil, err
		}
		r.bfReader.Discard(1)
		if b[0] == ',' {
			continue
		}
		if b[0] == '}' {
			return result, nil
		}
		FreeValue(result)
		return nil, ErrInvalidateJson
	}
}
